package com.chinaunicom.emergency.action;

import com.chinaunicom.emergency.annotation.Permission;
import com.chinaunicom.emergency.constant.ConstantUtil;
import com.chinaunicom.emergency.model.YjglOrg;
import com.chinaunicom.emergency.model.YjglUser;
import com.chinaunicom.emergency.service.OrgService;
import com.chinaunicom.emergency.util.Assert;
import com.chinaunicom.emergency.util.UpdateUtil;
import com.chinaunicom.emergency.exception.CheckException;
import com.chinaunicom.emergency.repository.OrgRepository;
import com.chinaunicom.emergency.repository.UsersRepository;
import com.chinaunicom.emergency.service.RedisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author liliang
 * @Date 2019/12/18 10:13
 * @Version 1.0
 */
@RestController
@Api(tags = {"组织机构管理"})
@RequestMapping("/api/org")
@Log4j2
@RefreshScope
public class OrgAction extends BaseAction {

    @Autowired
    OrgRepository orgRepository;
    @Autowired
    UsersRepository usersRepository;
    @Autowired
    RedisService redisService;
    @Autowired
    OrgService orgService;

    @ApiOperation("组织机构新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("org:add")
    @PostMapping(value = "/add")
    public Object add(@RequestBody YjglOrg org) throws CheckException {
        Assert.isBlank(org.getOrgName(), "机构名称不能为空");
        Assert.isBlank(org.getOrgId(), "机构编号不能为空");
        YjglOrg existOrg = orgRepository.findByParentIdAndOrgIdAndIsSoftDel(org.getParentId(),org.getOrgId(),0);
        Assert.isNotNull(existOrg,"该节点已存在编号的机构,请勿重复创建");
        YjglOrg existOrg1 = orgRepository.findByParentIdAndOrgNameAndIsSoftDel(org.getParentId(),org.getOrgName(),0);
        Assert.isNotNull(existOrg1,"该节点已存在名称的机构,请勿重复创建");

        org.setIsSoftDel(0);
        org.setCreateBy(getCurrUserId());
        org.setCreateTime(new Date());
        orgRepository.save(org);
        //异步将机构全称(-分隔)存储到缓存中
        orgService.updateRedis(false);
        return success();
    }

    @ApiOperation("组织机构修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("org:update")
    @PutMapping(value = "/update")
    public Object update(@RequestBody YjglOrg org) throws CheckException {
        Assert.isBlank(org.getOrgName(), "机构名称不能为空");
        Assert.isBlank(org.getOrgId(), "机构编号不能为空");
        YjglOrg thisOrg = orgRepository.findByPidAndIsSoftDel(org.getPid(),0);
        Assert.isNull(thisOrg,"该机构不存在,修改失败!");
        Assert.isNotEquals(thisOrg.getOrgId(),org.getOrgId(),"机构编号不允许修改,请重新填写!");
        Assert.isNotEquals(thisOrg.getParentId(),org.getParentId(),"上级机构不允许修改,请重新填写!");
        YjglOrg existOrg = orgRepository.findByParentIdAndOrgNameAndIsSoftDel(org.getParentId(),org.getOrgName(),0);
        if(null != existOrg){
            Assert.isNotEquals(existOrg.getOrgId(),org.getOrgId(),"用该节点已存在同名机构,请重新填写!");
        }
        //机构名称修改后,需要异步将机构全称(-分隔)存储到缓存中
        if(!thisOrg.getOrgName().equals(org.getOrgName())){
            orgService.updateRedis(false);
        }
        org.setUpdateBy(getCurrUserId());
        org.setUpdateTime(new Date());
        UpdateUtil.copyNullProperties(thisOrg,org);
        orgRepository.save(org);
        return success();
    }

    @ApiOperation("组织机构删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:delete")
    @DeleteMapping(value = "/delete")
    public Object delete(@RequestParam(value = "pid") String pid) throws CheckException {
        Assert.isBlank(pid, "机构id不能为空");
        YjglOrg thisOrg = orgRepository.findByPidAndIsSoftDel(pid,0);
        Assert.isNull(thisOrg,"该机构不存在,删除失败");
        List<String> orgChild = orgRepository.findOrgIdByParentId(pid);
        Assert.isNotNull(orgChild,"该机构下存在子机构,无法删除!");
        List<YjglUser> userList = usersRepository.findByOrgIdAndIsSoftDel(thisOrg.getOrgId(),0);
        Assert.isNotNull(userList,"该机构下存在用户,无法删除");

        thisOrg.setDeleteBy(getCurrUserId());
        thisOrg.setIsSoftDel(1);
        thisOrg.setDeleteTime(new Date());
        orgRepository.save(thisOrg);
        //机构名称删除后,需要将机构全称(-分隔)存储到缓存中
        redisService.deleteHashFields(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",thisOrg.getOrgId());
        return success();
    }


    @ApiOperation("单个组织机构明细查看")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("org:detail")
    @GetMapping(value = "/{pid}")
    public Object findByPid(@PathVariable String pid) throws CheckException {
        Assert.isBlank(pid, "机构id不能为空");
        YjglOrg org = orgRepository.findByPidAndIsSoftDel(pid,0);
        //TODO 需要设置机构全名称-拼接
        org.setOrgNameStr((String)redisService.getHash(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",org.getOrgId()));
        return success(org);
    }

    @ApiOperation("获取所有机构列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "token", required = true, paramType = "header", dataType = "String")
    })
    @Permission("org:all")
    @GetMapping(value = "/all")
    public Object getOrgAll() throws CheckException {
        List<YjglOrg> orgList = orgRepository.findAllByIsSoftDel(0);
        if(!CollectionUtils.isEmpty(orgList)){
            orgList.forEach(org ->{
                org.setOrgNameStr((String)redisService.getHash(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",org.getOrgId()));
            });
        }
        return success(orgList);
    }

    @ApiOperation("分页查看机构列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:page")
    @GetMapping(value = "/page")
    public Object findPage(@RequestParam(value = "limit", required = false) Integer limit,
                           @RequestParam(value = "page", required = false) Integer page,
                           @RequestParam(value = "rootId", required = false) String rootId,
                           @RequestParam(value = "orgName", required = false) String orgName
    ) throws CheckException {
        Map<String, Object> para = new HashMap<>();
        para.put("limit", limit == null ? 10 : limit);
        para.put("page", page == null ? 1 : page);
        para.put("isSoftDel", 0);
        para.put("orgName",orgName);
        if(StringUtils.isNotBlank(rootId)){
            para.put("parentId",rootId);
        }
        Sort sort = Sort.by(Sort.Direction.ASC, "orderNum");
        Page<YjglOrg> pages = orgRepository.findAll(orgService.findPageByCondition(para), getPageable(para, sort));
        if(null != pages){
            for (YjglOrg org : pages){
                if(null != org && StringUtils.isNotBlank(org.getOrgId())){
                    org.setOrgNameStr((String)redisService.getHash(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",org.getOrgId()));
                }
            }
        }
        return page(pages);
    }


    @ApiOperation("获取列表，可通过parentId查询，返回一层")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "token", required = true, paramType = "header", dataType = "String")
    })
    @Permission("org:listByParentId")
    @GetMapping(value = "/listByParentId")
    public Object getListByParentId(@RequestParam(value = "rootId", required = false) String rootId) throws CheckException {

        if (StringUtils.isBlank(rootId)) {
            rootId = null;
        }
        List<YjglOrg> orgList = orgRepository.findByParentIdAndIsSoftDelOrderByOrderNumAsc(rootId,0);
        if(!CollectionUtils.isEmpty(orgList)){
            orgList.forEach(org ->{
                org.setOrgNameStr((String)redisService.getHash(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",org.getOrgId()));
            });
        }
        return success(orgList);
    }

}
